import { defineStore } from 'pinia'
import axios from '../utils/axios'
import router from '../router'
import type { UpdateProfileRequest, UpdatePasswordRequest } from '../types/user'

export interface UserInfo {
  id: number;
  username: string;
  name: string;
  role: string;
  avatar?: string;
  email?: string;
}

interface UserState {
  user: {
    id: number | null
    name: string
    email: string
    roles: string[]
    realName?: string
    nickname?: string
    phone?: string
    bio?: string
    avatar?: string
  }
  token: string | null
  initialized: boolean
  error: string | null
  userInfo: UserInfo | null
  permissions: string[]
}

export const useUserStore = defineStore('user', {
  state: (): UserState => ({
    token: localStorage.getItem('token'),
    user: {
      id: null,
      name: '',
      email: '',
      roles: []
    },
    initialized: false,
    error: null,
    userInfo: null,
    permissions: []
  }),

  getters: {
    isLoggedIn: (state) => !!state.token,
    userId: (state) => state.user.id,
    isAdmin: (state) => {
      console.log('Checking admin permission, current roles:', state.user.roles)
      if (state.user.roles.includes('ADMIN')) {
        return true
      }
      return false
    },
    isSupervisor: (state) => {
      console.log('Checking supervisor permission, current roles:', state.user.roles)
      return state.user.roles.some((role: string) => 
        role === 'SUPERVISOR' || role === 'supervisor'
      )
    },
    isStudent: (state) => {
      console.log('Checking student permission, current roles:', state.user.roles)
      return state.user.roles.some((role: string) => 
        role === 'USER' || role === 'user'
      ) && !state.user.roles.some((role: string) => 
        role === 'ADMIN' || role === 'admin' || role === 'SUPERVISOR' || role === 'supervisor'
      )
    },
    getUserRole: (state) => {
      const role: string = state.user.roles[0]
      if (role === 'ADMIN') {
        return 'ADMIN'
      } else if (role === 'STAFF') {
        return 'STAFF'
      } else {
        return 'STUDENT'
      }
    },
    userRole(): string | null {
      return this.userInfo?.role || null;
    }
  },

  actions: {
    setAxiosAuthHeader() {
      if (this.token) {
        console.log('Setting global Authorization header:', this.token.substring(0, 10) + '...')
        axios.defaults.headers.common['Authorization'] = `Bearer ${this.token}`
      } else {
        console.log('Clearing global Authorization header')
        delete axios.defaults.headers.common['Authorization']
      }
    },

    async initializeAuth(): Promise<void> {
      if (this.initialized) return

      const token = localStorage.getItem('token')
      if (token) {
        console.log('Initializing auth, found token:', token.substring(0, 10) + '...')
        this.token = token
        this.setAxiosAuthHeader()
        
        try {
          await this.fetchUserInfo()
          console.log('Successfully fetched user info:', this.user)
        } catch (error) {
          console.error('Failed to fetch user info:', error)
          this.handleAuthError()
        }
      } else {
        console.log('Initializing auth, token not found')
      }
      
      this.initialized = true
    },

    handleAuthError() {
      console.log('Handling auth error, clearing user state')
      this.token = null
      this.user = {
        id: null,
        name: '',
        email: '',
        roles: []
      }
      localStorage.removeItem('token')
      this.setAxiosAuthHeader()
      
      if (router.currentRoute.value.meta.requiresAuth) {
        router.push('/login')
      }
    },

    async login(username: string, password: string) {
      try {
        this.error = null
        console.log('Starting login request, username:', username)
        
        const response = await axios.post('/api/auth/login', {
          username,
          password
        })
        
        console.log('Login response data:', JSON.stringify(response.data))
        
        // Data validation
        if (!response.data) {
          throw new Error('Server returned invalid data format')
        }
        
        if (!response.data.token) {
          throw new Error('Server response missing token')
        }
        
        this.token = response.data.token
        
        // Validate user data
        if (!response.data.user) {
          throw new Error('Server response missing user info')
        }
        
        this.user = {
          id: response.data.user.id || null,
          name: response.data.user.realName || response.data.user.username || '',
          email: response.data.user.email || '',
          roles: Array.isArray(response.data.user.roles) ? response.data.user.roles : [],
          realName: response.data.user.realName,
          nickname: response.data.user.nickname,
          phone: response.data.user.phone,
          bio: response.data.user.bio,
          avatar: response.data.user.avatar || ''
        }
        
        // Update userInfo as well
        this.userInfo = {
          id: response.data.user.id || 0,
          username: response.data.user.username || '',
          name: response.data.user.realName || response.data.user.username || '',
          role: Array.isArray(response.data.user.roles) && response.data.user.roles.length > 0 
            ? response.data.user.roles[0] 
            : 'USER',
          avatar: response.data.user.avatar || '',
          email: response.data.user.email || ''
        }
        
        localStorage.setItem('token', response.data.token)
        this.setAxiosAuthHeader()
        
        console.log('Login successful, user roles:', this.user.roles)
        
        this.redirectBasedOnRole()

        return true
      } catch (error: any) {
        console.error('Login failed:', error)
        console.error('Error details:', error.stack)
        
        if (error.response) {
          console.error('Response status:', error.response.status)
          console.error('Response data:', JSON.stringify(error.response.data))
        }
        
        if (error.response?.data?.message) {
          this.error = error.response.data.message
        } else if (error.message) {
          this.error = `Login failed: ${error.message}`
        } else {
          this.error = 'Login failed, please try again later'
        }
        
        return false
      }
    },

    redirectBasedOnRole() {
      console.log('Executing role-based redirect, user roles:', this.user.roles)
      if (this.isAdmin) {
        console.log('User is admin, redirecting to admin dashboard')
        router.push('/admin/dashboard')
      } else if (this.isSupervisor) {
        console.log('User is supervisor, redirecting to supervisor console')
        router.push('/supervisor/dashboard')
      } else {
        console.log('User is regular user, redirecting to dashboard')
        router.push('/dashboard')
      }
    },

    async register(userData: {
      username: string, 
      password: string,
      realName: string,
      nickname: string,
      email: string,
      phone: string
    }) {
      try {
        this.error = null
        await axios.post('/api/auth/register', userData)
        return true
      } catch (error: any) {
        console.error('Registration failed:', error)
        
        if (error.response?.data?.message) {
          this.error = error.response.data.message
        } else if (error.message) {
          this.error = `Registration failed: ${error.message}`
        } else {
          this.error = 'Registration failed, please try again later'
        }
        
        return false
      }
    },

    async fetchUserInfo(forceRefresh = false) {
      if (!this.token) {
        console.log('Failed to fetch user info: token not found')
        return false
      }
      
      try {
        console.log('Starting to fetch user info...')
        const timestamp = forceRefresh ? `?_t=${Date.now()}` : ''
        const response = await axios.get(`/api/auth/info${timestamp}`)
        
        this.user = response.data.user
        console.log('User info fetched successfully:', this.user.name, 'roles:', this.user.roles)
        return true
      } catch (error: any) {
        console.error('Failed to fetch user info:', error.message || error)
        
        if (error.response?.status !== 401 || forceRefresh) {
          throw error
        }
        
        return false
      }
    },
    
    async updateProfile(profileData: UpdateProfileRequest) {
      try {
        this.error = null
        console.log('Starting to update profile:', JSON.stringify(profileData))
        
        const response = await axios.put('/api/user/profile', profileData)
        
        console.log('Profile update response data:', JSON.stringify(response.data))
        
        // Data validation
        if (!response.data) {
          throw new Error('Server returned invalid data format')
        }
        
        if (response.data && response.data.user) {
          // Create a new user object, ensure deep merge
          const updatedUser = response.data.user
          
          // Update user info, preserve fields that were not updated
          this.user = { 
            ...this.user,
            id: updatedUser.id || this.user.id,
            name: updatedUser.realName || updatedUser.username || this.user.name,
            email: updatedUser.email || this.user.email,
            realName: updatedUser.realName || this.user.realName,
            nickname: updatedUser.nickname || this.user.nickname,
            phone: updatedUser.phone || this.user.phone,
            bio: updatedUser.bio || this.user.bio,
            avatar: updatedUser.avatar || this.user.avatar,
            // Ensure roles array is properly handled
            roles: Array.isArray(updatedUser.roles) ? updatedUser.roles : this.user.roles
          }
          
          console.log('Profile updated successfully, updated user info:', JSON.stringify(this.user))
        }
        
        return true
      } catch (error: any) {
        console.error('Failed to update profile:', error)
        
        if (error.response?.data?.message) {
          this.error = error.response.data.message
        } else if (error.message) {
          this.error = `Failed to update profile: ${error.message}`
        } else {
          this.error = 'Failed to update profile, please try again later'
        }
        
        return false
      }
    },
    
    async updateAvatar(avatarUrl: string): Promise<boolean> {
      try {
        console.log('Starting to update avatar URL:', avatarUrl)
        this.error = null
        
        if (!avatarUrl || typeof avatarUrl !== 'string') {
          console.error('Invalid avatar URL format:', avatarUrl)
          this.error = 'Invalid avatar URL format'
          return false
        }
        
        // Update user avatar
        this.user.avatar = avatarUrl
        
        // You can choose to call a backend API to save the avatar URL
        // but typically this is already handled by the server during upload
        console.log('Avatar URL updated successfully:', avatarUrl)
        return true
      } catch (error: any) {
        console.error('Failed to update avatar:', error)
        
        if (error.message) {
          this.error = `Failed to update avatar: ${error.message}`
        } else {
          this.error = 'Failed to update avatar, please try again later'
        }
        
        return false
      }
    },

    async changePassword(data: UpdatePasswordRequest) {
      try {
        await axios.post('/api/auth/change-password', data)
        return true
      } catch (error) {
        console.error('Failed to change password:', error)
        throw error
      }
    },

    logout() {
      this.token = null
      this.user = {
        id: null,
        name: '',
        email: '',
        roles: []
      }
      this.userInfo = null
      localStorage.removeItem('token')
      this.setAxiosAuthHeader()
      
      // Importing methods from webSocket service would cause circular dependency
      // Let the watch listener in App.vue handle the connection closing
      
      router.push('/login')
    },

    setToken(token: string) {
      this.token = token;
      localStorage.setItem('token', token);
    },
    
    setUserInfo(userInfo: UserInfo) {
      this.userInfo = userInfo;
    },
    
    setPermissions(permissions: string[]) {
      this.permissions = permissions;
    },
    
    clearUserInfo() {
      this.userInfo = null;
      this.token = '';
      this.permissions = [];
      localStorage.removeItem('token');
    },
    
    // Directly set user avatar URL
    setUserAvatar(avatarUrl: string) {
      if (!avatarUrl || typeof avatarUrl !== 'string') {
        console.error('Invalid avatar URL format:', avatarUrl);
        return;
      }
      
      // Update user avatar
      this.user.avatar = avatarUrl;
      
      // If userInfo exists, update it as well
      if (this.userInfo) {
        this.userInfo.avatar = avatarUrl;
      }
      
      console.log('Avatar URL updated successfully:', avatarUrl);
    }
  }
})